package com.example.cloud.service.business.medical.impl;

import com.example.cloud.constants.CommonConstants;
import com.example.cloud.constants.StateConstants;
import com.example.cloud.dao.business.medical.TreatPlanHomeDiscountProductDetailsRepository;
import com.example.cloud.dao.business.medical.TreatPlanHomeDiscountProductRepository;
import com.example.cloud.dao.business.medical.TreatPlanHomeDiscountProjectDetailsRepository;
import com.example.cloud.dao.business.medical.TreatPlanHomeDiscountProjectRepository;
import com.example.cloud.dao.business.medical.TreatPlanHomeProductRepository;
import com.example.cloud.dao.business.medical.TreatPlanHomeProjectRepository;
import com.example.cloud.dao.business.medical.TreatPlanHomeRepository;
import com.example.cloud.dao.finance.ChargeDetailsRepository;
import com.example.cloud.model.basic.HomeProduct;
import com.example.cloud.model.basic.HomeProject;
import com.example.cloud.model.business.medical.TreatPlanHome;
import com.example.cloud.model.business.medical.TreatPlanHomeDiscountProduct;
import com.example.cloud.model.business.medical.TreatPlanHomeDiscountProductDetails;
import com.example.cloud.model.business.medical.TreatPlanHomeDiscountProject;
import com.example.cloud.model.business.medical.TreatPlanHomeDiscountProjectDetails;
import com.example.cloud.model.business.medical.TreatPlanHomeProduct;
import com.example.cloud.model.business.medical.TreatPlanHomeProject;
import com.example.cloud.model.dto.Result;
import com.example.cloud.model.finance.ChargeDetails;
import com.example.cloud.model.member.Member;
import com.example.cloud.service.basic.info.*;
import com.example.cloud.service.business.medical.TreatPlanHomeService;
import com.example.cloud.utils.BusinessUtil;
import com.example.cloud.utils.DateUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by wangtao on 2018/6/6.
 */
@Service
public class TreatPlanHomeServiceImpl implements TreatPlanHomeService {

    private static final Logger logger = Logger.getLogger(TreatPlanHomeServiceImpl.class);

    @PersistenceContext
    EntityManager em;

    @Autowired
    private ProductService productService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private HomeService homeService;

    @Autowired
    private HomeProductService homeProductService;

    @Autowired
    private HomeProjectService homeProjectService;

    @Autowired
    private HomeDiscountProductService homeDiscountProductService;

    @Autowired
    private HomeDiscountProductDetailsService homeDiscountProductDetailsService;

    @Autowired
    private HomeDiscountProjectService homeDiscountProjectService;

    @Autowired
    private HomeDiscountProjectDetailsService homeDiscountProjectDetailsService;

    @Autowired
    private TreatPlanHomeRepository treatPlanHomeRepository;

    @Autowired
    private TreatPlanHomeProjectRepository treatPlanHomeProjectRepository;

    @Autowired
    private TreatPlanHomeProductRepository treatPlanHomeProductRepository;

    @Autowired
    private TreatPlanHomeDiscountProjectRepository discountProjectRepository;

    @Autowired
    private TreatPlanHomeDiscountProjectDetailsRepository discountProjectDetailsRepository;

    @Autowired
    private TreatPlanHomeDiscountProductRepository discountProductRepository;

    @Autowired
    private TreatPlanHomeDiscountProductDetailsRepository discountProductDetailsRepository;

    @Override
    public TreatPlanHome findOne(Long id) {
        return treatPlanHomeRepository.findOne(id);
    }

    @Autowired
    private MemberService memberService;

    @Autowired
    private ChargeDetailsRepository chargeDetailsRepository;

    @Override
    @Transactional
    public void batchInsert(List<TreatPlanHome> records, Long patientId) {
        for (TreatPlanHome record : records) {
            record.setId(null);
            record.setPatientId(patientId);
            // 设置会员信息
            ChargeDetails details = new ChargeDetails();
            Member member = memberService.findByPatientId(patientId);
            if(member != null){
                record.setMemberId(member.getId());
                details.setMemberId(member.getId());
            }
            record.setStatus(StateConstants.HOME_STATUS_ACTIVE);
            record.setCreationTime(null);
            BusinessUtil.appendRecord(record);
            record = treatPlanHomeRepository.save(record);
            Long homeId = record.getId();
            if(record.getProjects() != null){
                List<List<TreatPlanHomeProject>> projects = record.getProjects();
                if(!projects.isEmpty() && projects.size() > 0){
                    // 基本项目
                    List<TreatPlanHomeProject> basicProject = projects.get(0) == null ? new ArrayList<>() : projects.get(0);
                    if(basicProject.isEmpty()){
                        List<HomeProject> homeProjects = homeProjectService.findBasicPlanFromCache(record.getHomeId());
                        if(!homeProjects.isEmpty()){
                            for (HomeProject homeProject : homeProjects) {
                                TreatPlanHomeProject planHomeProject = new TreatPlanHomeProject();
                                planHomeProject.setPatientId(record.getPatientId());
                                planHomeProject.setMemberId(record.getMemberId());
                                planHomeProject.setComplaintId(record.getComplaintId());
                                planHomeProject.setHomeId(homeId);
                                planHomeProject.setPlanType(homeProject.getPlanType());
                                planHomeProject.setProjectId(homeProject.getProjectId());
                                planHomeProject.setProjectName(homeProject.getProjectName());
                                planHomeProject.setPrice(homeProject.getPrice());
                                planHomeProject.setQuantity(homeProject.getQuantity());
                                planHomeProject.setTotalPrice(planHomeProject.getPrice().multiply(new BigDecimal(planHomeProject.getQuantity())));
                                planHomeProject.setStatus(StateConstants.HOME_DETAILS_STATUS_PROCESS);
                                planHomeProject.setCreationTime(null);
                                BusinessUtil.appendRecord(planHomeProject);
                                basicProject.add(planHomeProject);
                            }
                            treatPlanHomeProjectRepository.save(basicProject);
                        }
                    }else{
                        for (TreatPlanHomeProject project : basicProject) {
                            project.setId(null);
                            project.setPatientId(record.getPatientId());
                            project.setMemberId(record.getMemberId());
                            project.setComplaintId(record.getComplaintId());
                            project.setHomeId(homeId);
                            project.setTotalPrice(project.getPrice().multiply(new BigDecimal(project.getQuantity())));
                            project.setStatus(StateConstants.HOME_DETAILS_STATUS_PROCESS);
                            project.setCreationTime(null);
                            BusinessUtil.appendRecord(project);
                        }
                        treatPlanHomeProjectRepository.save(basicProject);
                    }
                }
                if(!projects.isEmpty() && projects.size() > 1){
                    // 可选项目
                    List<TreatPlanHomeProject> optionalProjects = projects.get(1) == null ? new ArrayList<>() : projects.get(1);
                    if(!optionalProjects.isEmpty()){
                        for (TreatPlanHomeProject project : optionalProjects) {
                            project.setId(null);
                            project.setPatientId(record.getPatientId());
                            project.setMemberId(record.getMemberId());
                            project.setComplaintId(record.getComplaintId());
                            project.setHomeId(homeId);
                            project.setTotalPrice(project.getPrice().multiply(new BigDecimal(project.getQuantity())));
                            project.setStatus(StateConstants.HOME_DETAILS_STATUS_PROCESS);
                            project.setCreationTime(null);
                            BusinessUtil.appendRecord(project);
                        }
                        treatPlanHomeProjectRepository.save(optionalProjects);
                    }
                }
            }else{
                List<TreatPlanHomeProject> basicProject = new ArrayList<>();
                List<HomeProject> homeProjects = homeProjectService.findBasicPlanFromCache(record.getHomeId());
                if(!homeProjects.isEmpty()){
                    for (HomeProject homeProject : homeProjects) {
                        TreatPlanHomeProject planHomeProject = new TreatPlanHomeProject();
                        planHomeProject.setPatientId(record.getPatientId());
                        planHomeProject.setMemberId(record.getMemberId());
                        planHomeProject.setComplaintId(record.getComplaintId());
                        planHomeProject.setHomeId(homeId);
                        planHomeProject.setPlanType(homeProject.getPlanType());
                        planHomeProject.setProjectId(homeProject.getProjectId());
                        planHomeProject.setProjectName(homeProject.getProjectName());
                        planHomeProject.setPrice(homeProject.getPrice());
                        planHomeProject.setQuantity(homeProject.getQuantity());
                        planHomeProject.setTotalPrice(planHomeProject.getPrice().multiply(new BigDecimal(planHomeProject.getQuantity())));
                        planHomeProject.setStatus(StateConstants.HOME_DETAILS_STATUS_PROCESS);
                        planHomeProject.setCreationTime(null);
                        BusinessUtil.appendRecord(planHomeProject);
                        basicProject.add(planHomeProject);
                    }
                    treatPlanHomeProjectRepository.save(basicProject);
                }
            }
            if(record.getProducts() != null){
                List<List<TreatPlanHomeProduct>> products = record.getProducts();
                if(!products.isEmpty() && products.size() > 0){
                    // 基本产品
                    List<TreatPlanHomeProduct> basicProduct = products.get(0) == null ? new ArrayList<>() : products.get(0);
                    if(basicProduct.isEmpty()){
                        List<HomeProduct> homeProducts = homeProductService.findBasicPlanFromCache(record.getHomeId());
                        if(!homeProducts.isEmpty()){
                            for (HomeProduct homeProduct : homeProducts) {
                                TreatPlanHomeProduct planHomeProduct = new TreatPlanHomeProduct();
                                planHomeProduct.setPatientId(record.getPatientId());
                                planHomeProduct.setMemberId(record.getMemberId());
                                planHomeProduct.setComplaintId(record.getComplaintId());
                                planHomeProduct.setHomeId(homeId);
                                planHomeProduct.setPlanType(homeProduct.getPlanType());
                                planHomeProduct.setProductId(homeProduct.getProductId());
                                planHomeProduct.setProductName(homeProduct.getProductName());
                                planHomeProduct.setPrice(homeProduct.getPrice());
                                planHomeProduct.setQuantity(homeProduct.getQuantity());
                                planHomeProduct.setTotalPrice(planHomeProduct.getPrice().multiply(new BigDecimal(planHomeProduct.getQuantity())));
                                planHomeProduct.setStatus(StateConstants.HOME_DETAILS_STATUS_PROCESS);
                                planHomeProduct.setCreationTime(null);
                                BusinessUtil.appendRecord(planHomeProduct);
                                basicProduct.add(planHomeProduct);
                            }
                            treatPlanHomeProductRepository.save(basicProduct);
                        }
                    }else{
                        for (TreatPlanHomeProduct product : basicProduct) {
                            product.setId(null);
                            product.setPatientId(record.getPatientId());
                            product.setMemberId(record.getMemberId());
                            product.setComplaintId(record.getComplaintId());
                            product.setHomeId(homeId);
                            product.setTotalPrice(product.getPrice().multiply(new BigDecimal(product.getQuantity())));
                            product.setStatus(StateConstants.HOME_DETAILS_STATUS_PROCESS);
                            product.setCreationTime(null);
                            BusinessUtil.appendRecord(product);
                        }
                        treatPlanHomeProductRepository.save(basicProduct);
                    }
                }
                if(!products.isEmpty() && products.size() > 1){
                    // 可选产品
                    List<TreatPlanHomeProduct> optionalProducts = products.get(1) == null ? new ArrayList<>() : products.get(1);
                    if(!optionalProducts.isEmpty()){
                        for (TreatPlanHomeProduct product : optionalProducts) {
                            product.setId(null);
                            product.setPatientId(record.getPatientId());
                            product.setMemberId(record.getMemberId());
                            product.setComplaintId(record.getComplaintId());
                            product.setHomeId(homeId);
                            product.setTotalPrice(product.getPrice().multiply(new BigDecimal(product.getQuantity())));
                            product.setStatus(StateConstants.HOME_DETAILS_STATUS_PROCESS);
                            product.setCreationTime(null);
                            BusinessUtil.appendRecord(product);
                        }
                        treatPlanHomeProductRepository.save(optionalProducts);
                    }
                }
            }else{
                List<TreatPlanHomeProduct> basicProduct = new ArrayList<>();
                List<HomeProduct> homeProducts = homeProductService.findBasicPlanFromCache(record.getHomeId());
                if(!homeProducts.isEmpty()){
                    for (HomeProduct homeProduct : homeProducts) {
                        TreatPlanHomeProduct planHomeProduct = new TreatPlanHomeProduct();
                        planHomeProduct.setPatientId(record.getPatientId());
                        planHomeProduct.setMemberId(record.getMemberId());
                        planHomeProduct.setComplaintId(record.getComplaintId());
                        planHomeProduct.setHomeId(homeId);
                        planHomeProduct.setPlanType(homeProduct.getPlanType());
                        planHomeProduct.setProductId(homeProduct.getProductId());
                        planHomeProduct.setProductName(homeProduct.getProductName());
                        planHomeProduct.setPrice(homeProduct.getPrice());
                        planHomeProduct.setQuantity(homeProduct.getQuantity());
                        planHomeProduct.setTotalPrice(planHomeProduct.getPrice().multiply(new BigDecimal(planHomeProduct.getQuantity())));
                        planHomeProduct.setStatus(StateConstants.HOME_DETAILS_STATUS_PROCESS);
                        planHomeProduct.setCreationTime(null);
                        BusinessUtil.appendRecord(planHomeProduct);
                        basicProduct.add(planHomeProduct);
                    }
                    treatPlanHomeProductRepository.save(basicProduct);
                }
            }
            // 保存折扣项目类型
            if(record.getDiscountProjects() != null){
                List<TreatPlanHomeDiscountProject> discountProjects = record.getDiscountProjects();
                if(!discountProjects.isEmpty()){
                    for (TreatPlanHomeDiscountProject discountProject : discountProjects) {
                        discountProject.setId(null);
                        discountProject.setHomeId(homeId);
                        discountProject.setCreationTime(null);
                        BusinessUtil.appendRecord(discountProject);
                    }
                    discountProjectRepository.save(discountProjects);
                }
            }
            // 保存折扣项目明细
            if(record.getDiscountProjectDetails() != null){
                List<TreatPlanHomeDiscountProjectDetails> discountProjectDetails = record.getDiscountProjectDetails();
                if(!discountProjectDetails.isEmpty()){
                    for (TreatPlanHomeDiscountProjectDetails discountProjectDetail : discountProjectDetails) {
                        discountProjectDetail.setId(null);
                        discountProjectDetail.setHomeId(homeId);
                        discountProjectDetail.setCreationTime(null);
                        BusinessUtil.appendRecord(discountProjectDetail);
                    }
                    discountProjectDetailsRepository.save(discountProjectDetails);
                }
            }
            // 保存折扣产品
            if(record.getDiscountProducts() != null){
                List<TreatPlanHomeDiscountProduct> discountProducts = record.getDiscountProducts();
                if(!discountProducts.isEmpty()){
                    for (TreatPlanHomeDiscountProduct discountProduct : discountProducts) {
                        discountProduct.setId(null);
                        discountProduct.setHomeId(homeId);
                        discountProduct.setCreationTime(null);
                        BusinessUtil.appendRecord(discountProduct);
                    }
                    discountProductRepository.save(discountProducts);
                }
            }
            // 保存折扣产品明细
            if(record.getDiscountProductDetails() != null){
                List<TreatPlanHomeDiscountProductDetails> discountProductDetails = record.getDiscountProductDetails();
                if(!discountProductDetails.isEmpty()){
                    for (TreatPlanHomeDiscountProductDetails discountProductDetail : discountProductDetails) {
                        discountProductDetail.setId(null);
                        discountProductDetail.setHomeId(homeId);
                        discountProductDetail.setCreationTime(null);
                        BusinessUtil.appendRecord(discountProductDetail);
                    }
                    discountProductDetailsRepository.save(discountProductDetails);
                }
            }
            // 创建收费
            generateChargeDetails(record, patientId, details);
        }
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void generateChargeDetails(TreatPlanHome record, Long patientId, ChargeDetails details){
        details.setPatientId(patientId);
        details.setBusinessId(record.getId());
        details.setBusinessType(StateConstants.CHARGE_BUSINESS_TYPE_HOME);
        details.setChargeType(StateConstants.CHARGE_CHARGE_TYPE_HOME);
        details.setItemId(record.getHomeId());
        details.setItemName(record.getHomeName());
        details.setQuantity(record.getQuantity());
        details.setPrice(record.getPrice());
        details.setTotalPrice(record.getTotalPrice());
        details.setIsRenew(record.getIsRenewal());
        details.setCreationTime(null);
        BusinessUtil.appendRecord(details);
        chargeDetailsRepository.save(details);
    }

    @Override
    @Transactional
    public Result doDeleteById(Long id) {
        Result result = new Result();
        result.setCode(CommonConstants.SUCCESS);
        result.setMsg("删除成功");
        // 校验删除条件
        boolean check = checkDelete(id);
        if(!check){
            result.setCode(CommonConstants.FAILURE);
            result.setMsg("购买成功后不能删除");
            return result;
        }
        // 逻辑删除
        treatPlanHomeRepository.delete(id);
        // 删除治疗方案下的所有明细
        treatPlanHomeProductRepository.deleteByHomeId(id);
        treatPlanHomeProjectRepository.deleteByHomeId(id);
        discountProductRepository.deleteByHomeId(id);
        discountProductDetailsRepository.deleteByHomeId(id);
        discountProjectRepository.deleteByHomeId(id);
        discountProjectDetailsRepository.deleteByHomeId(id);
        // 删除待收费
        chargeDetailsRepository.deleteByBusinessIdAndChargeType(id, StateConstants.CHARGE_CHARGE_TYPE_HOME);
        return result;
    }

    public boolean checkDelete(Long id){
        boolean check = true;
        TreatPlanHome record = treatPlanHomeRepository.findOne(id);
        // 已付款不能删除
        if(record.getChargeStatus() == StateConstants.CHARGE_STATUS_YES){
            check = false;
        }
        return check;
    }

    @Override
    @Transactional
    public void doDelete(List<Long> ids) {
        // 逻辑删除
        StringBuilder sql = new StringBuilder("update treat_plan_home set delete_flag = 1 where id in(:ids)");
        Query query = em.createNativeQuery(sql.toString());
        query.setParameter("ids", ids);
        query.executeUpdate();
    }

    @Override
    @Transactional(isolation = Isolation.DEFAULT)
    public Result doFreeze(Long id) {
        Result result = new Result();
        result.setCode(CommonConstants.SUCCESS);
        TreatPlanHome ph = treatPlanHomeRepository.findOne(id);
        if(ph != null){
            if(ph.getChargeStatus() != StateConstants.CHARGE_STATUS_YES){
                result.setCode(CommonConstants.FAILURE);
                result.setMsg("未付款状态下不能冻结");
                return result;
            }
            if(ph.getStatus() != StateConstants.HOME_STATUS_ACTIVE){
                result.setCode(CommonConstants.FAILURE);
                result.setMsg("不符合冻结条件");
                return result;
            }
            ph.setStatus(StateConstants.HOME_STATUS_FREEZE);
            ph.setFreezeTime(new Date());
            BusinessUtil.appendRecord(ph);
            treatPlanHomeRepository.save(ph);
        }
        return result;
    }

    @Override
    @Transactional(isolation = Isolation.DEFAULT)
    public Result doActive(Long id) {
        Result result = new Result();
        result.setCode(CommonConstants.SUCCESS);
        TreatPlanHome ph = treatPlanHomeRepository.findOne(id);
        if(ph != null){
            if(ph.getStatus() != StateConstants.HOME_STATUS_FREEZE){
                result.setCode(CommonConstants.FAILURE);
                result.setMsg("不符合激活条件");
                return result;
            }
            // 上次冻结时间
            Date d1 = ph.getFreezeTime();
            // 本次激活时间
            Date d2 = new Date();
            // 本次激活时间和上次冻结时间相差天数
            int days = DateUtils.differentDaysByMillisecond(d1, d2);
            // 重新计算过期时间
            Date expiredDate = ph.getExpiredDate();
            expiredDate = DateUtils.addDays(expiredDate, days);
            ph.setExpiredDate(expiredDate);
            ph.setStatus(StateConstants.HOME_STATUS_ACTIVE);
            BusinessUtil.appendRecord(ph);
            treatPlanHomeRepository.save(ph);
        }
        return result;
    }

    @Override
    @Transactional
    public void doModify(Long id, BigDecimal totalPrice) {
        StringBuilder sql = new StringBuilder("update treat_plan_home set total_price = :price where id = :id");
        Query q = em.createNativeQuery(sql.toString());
        q.setParameter("price", totalPrice);
        q.setParameter("id", id);
        q.executeUpdate();
    }
}
